import { IDBStore } from './store'
import { IDBDataType } from './types'

export class IDBStoreCreate {
  idbStore: IDBStore
  constructor(idbStore: IDBStore) {
    this.idbStore = idbStore
  }

  /**
   * 创建一条记录
   * @param record 记录, 包含主键
   * @returns void
   */
  create(record: IDBDataType): Promise<void> {
    const db = this.idbStore.getDB()
    const storeName = this.idbStore.getStoreName()
    const transaction = db.transaction(storeName, 'readwrite')
    const store = transaction.objectStore(storeName)
    const req = store.add(record)
    return new Promise(function (resolve, reject) {
      req.onsuccess = function () {
        // 注意这里的 target.result 只是主键值，不是完整的记录
        // const target = evt.target as IDBRequest
        resolve()
      }
      req.onerror = function (evt) {
        const target = evt.target as IDBRequest
        reject(target.error)
      }
    })
  }

  /**
   * 批量创建记录
   * @param records 记录列表
   * @returns 返回插入失败的记录列表
   */
  bulkCreate(records: IDBDataType[]): Promise<IDBDataType[]> {
    const db = this.idbStore.getDB()
    const storeName = this.idbStore.getStoreName()
    const transaction = db.transaction(storeName, 'readwrite')
    const store = transaction.objectStore(storeName)
    const failedRecords: IDBDataType[] = []
    records.forEach((record) => {
      const req = store.add(record)
      req.onerror = () => {
        failedRecords.push(record)
      }
    })
    return new Promise(function (resolve, reject) {
      transaction.oncomplete = function () {
        resolve(failedRecords)
      }
      // 备注: 如果主动调用 transaction.abort() 取消, 是先触发 onerror 事件后触发 onabort 事件
      // 错误通常是由 request onerror 发起, 冒泡给 transaction onerror 的, 这样的错误通常不需要处理 onabort 事件.
      // 但是有例外, 如果这个错误和特定 request 无关, 如 Quota exceeded 超出配额, 磁盘 I/O 错误, 那么需要主动留意 onabort 的处理.
      transaction.onabort = function (evt) {
        const target = evt.target as IDBTransaction
        if (target.error instanceof Error) {
          reject(target.error)
        } else {
          reject(new Error('TransactionAborted'))
        }
      }
      transaction.onerror = function (evt) {
        const target = evt.target as IDBRequest
        reject(target.error)
      }
    })
  }
}
